/*
 * utils.c
 *
 *  Created on: 2017年3月21日
 *      Author: chenshisheng
 */

#include "utils.h"
#include "message_queue.h"

#include <stdlib.h>
#include <ctype.h>

#define _sdata __data_start__
#define _edata __data_end__

// 在链接脚本内定义的内存的BSS段及DATA段的地址范围变量
extern unsigned int  __bss_start__, __bss_end__;
extern unsigned int _sdata, _edata;

#define BSS_START  ((void *) & __bss_start__)
#define BSS_END    ((void *) & __bss_end__)
#define DATA_START ((void *) & _sdata)
#define DATA_END   ((void *) & _edata)

#if 0
void HAL_Delay(uint32_t ms)
{
    uint32_t tickstart = HAL_GetTick();
    uint32_t wait = ms;

    /* Add a period to guaranty minimum wait */
    if(wait < HAL_MAX_DELAY)
    {
    	wait += uwTickFreq;
    }

    while((HAL_GetTick() - tickstart) < wait)
    {
        IDLE();
    }
}
#endif

/**
 * @brief 判断一个变量是不是全局变量
 * @param varAddr 变量的地址（指针）
 * @return TRUE 是全局变量
 *         FALSE 不是全局变量
 */
bool Utils_IsGlobalVariable(void *varAddr)
{
    if((varAddr <= BSS_START) && (varAddr > BSS_END) &&
            (varAddr <= DATA_START) && (varAddr > DATA_END))
    {
        return FALSE;
    }
    else
    {
        return TRUE;
    }
}

// polynomial: 0x11021
uint16_t Utils_Crc16Xmodem(uint16_t init, const void *data, unsigned int size)
{
    const uint8_t *vdata = data;
    uint16_t crc = init;
    static const uint16_t table[256] =
    {
        0x0000U,0x1021U,0x2042U,0x3063U,0x4084U,0x50A5U,0x60C6U,0x70E7U,
        0x8108U,0x9129U,0xA14AU,0xB16BU,0xC18CU,0xD1ADU,0xE1CEU,0xF1EFU,
        0x1231U,0x0210U,0x3273U,0x2252U,0x52B5U,0x4294U,0x72F7U,0x62D6U,
        0x9339U,0x8318U,0xB37BU,0xA35AU,0xD3BDU,0xC39CU,0xF3FFU,0xE3DEU,
        0x2462U,0x3443U,0x0420U,0x1401U,0x64E6U,0x74C7U,0x44A4U,0x5485U,
        0xA56AU,0xB54BU,0x8528U,0x9509U,0xE5EEU,0xF5CFU,0xC5ACU,0xD58DU,
        0x3653U,0x2672U,0x1611U,0x0630U,0x76D7U,0x66F6U,0x5695U,0x46B4U,
        0xB75BU,0xA77AU,0x9719U,0x8738U,0xF7DFU,0xE7FEU,0xD79DU,0xC7BCU,
        0x48C4U,0x58E5U,0x6886U,0x78A7U,0x0840U,0x1861U,0x2802U,0x3823U,
        0xC9CCU,0xD9EDU,0xE98EU,0xF9AFU,0x8948U,0x9969U,0xA90AU,0xB92BU,
        0x5AF5U,0x4AD4U,0x7AB7U,0x6A96U,0x1A71U,0x0A50U,0x3A33U,0x2A12U,
        0xDBFDU,0xCBDCU,0xFBBFU,0xEB9EU,0x9B79U,0x8B58U,0xBB3BU,0xAB1AU,
        0x6CA6U,0x7C87U,0x4CE4U,0x5CC5U,0x2C22U,0x3C03U,0x0C60U,0x1C41U,
        0xEDAEU,0xFD8FU,0xCDECU,0xDDCDU,0xAD2AU,0xBD0BU,0x8D68U,0x9D49U,
        0x7E97U,0x6EB6U,0x5ED5U,0x4EF4U,0x3E13U,0x2E32U,0x1E51U,0x0E70U,
        0xFF9FU,0xEFBEU,0xDFDDU,0xCFFCU,0xBF1BU,0xAF3AU,0x9F59U,0x8F78U,
        0x9188U,0x81A9U,0xB1CAU,0xA1EBU,0xD10CU,0xC12DU,0xF14EU,0xE16FU,
        0x1080U,0x00A1U,0x30C2U,0x20E3U,0x5004U,0x4025U,0x7046U,0x6067U,
        0x83B9U,0x9398U,0xA3FBU,0xB3DAU,0xC33DU,0xD31CU,0xE37FU,0xF35EU,
        0x02B1U,0x1290U,0x22F3U,0x32D2U,0x4235U,0x5214U,0x6277U,0x7256U,
        0xB5EAU,0xA5CBU,0x95A8U,0x8589U,0xF56EU,0xE54FU,0xD52CU,0xC50DU,
        0x34E2U,0x24C3U,0x14A0U,0x0481U,0x7466U,0x6447U,0x5424U,0x4405U,
        0xA7DBU,0xB7FAU,0x8799U,0x97B8U,0xE75FU,0xF77EU,0xC71DU,0xD73CU,
        0x26D3U,0x36F2U,0x0691U,0x16B0U,0x6657U,0x7676U,0x4615U,0x5634U,
        0xD94CU,0xC96DU,0xF90EU,0xE92FU,0x99C8U,0x89E9U,0xB98AU,0xA9ABU,
        0x5844U,0x4865U,0x7806U,0x6827U,0x18C0U,0x08E1U,0x3882U,0x28A3U,
        0xCB7DU,0xDB5CU,0xEB3FU,0xFB1EU,0x8BF9U,0x9BD8U,0xABBBU,0xBB9AU,
        0x4A75U,0x5A54U,0x6A37U,0x7A16U,0x0AF1U,0x1AD0U,0x2AB3U,0x3A92U,
        0xFD2EU,0xED0FU,0xDD6CU,0xCD4DU,0xBDAAU,0xAD8BU,0x9DE8U,0x8DC9U,
        0x7C26U,0x6C07U,0x5C64U,0x4C45U,0x3CA2U,0x2C83U,0x1CE0U,0x0CC1U,
        0xEF1FU,0xFF3EU,0xCF5DU,0xDF7CU,0xAF9BU,0xBFBAU,0x8FD9U,0x9FF8U,
        0x6E17U,0x7E36U,0x4E55U,0x5E74U,0x2E93U,0x3EB2U,0x0ED1U,0x1EF0U,
    };

    while (size > 0)
    {
        crc = table[*vdata ^ (uint8_t)(crc >> 8)] ^ (crc << 8);
        vdata++;
        size--;
    }

    return crc;
}

// polynomial: 0x18005, bit reverse algorithm
uint16_t Utils_CRC16Modbus(const void *dataIn, unsigned int size)
{
    const uint8_t *data = dataIn;
    uint16_t crc = 0xffff;
    static const uint16_t table[256] = {
    0x0000U,0xC0C1U,0xC181U,0x0140U,0xC301U,0x03C0U,0x0280U,0xC241U,
    0xC601U,0x06C0U,0x0780U,0xC741U,0x0500U,0xC5C1U,0xC481U,0x0440U,
    0xCC01U,0x0CC0U,0x0D80U,0xCD41U,0x0F00U,0xCFC1U,0xCE81U,0x0E40U,
    0x0A00U,0xCAC1U,0xCB81U,0x0B40U,0xC901U,0x09C0U,0x0880U,0xC841U,
    0xD801U,0x18C0U,0x1980U,0xD941U,0x1B00U,0xDBC1U,0xDA81U,0x1A40U,
    0x1E00U,0xDEC1U,0xDF81U,0x1F40U,0xDD01U,0x1DC0U,0x1C80U,0xDC41U,
    0x1400U,0xD4C1U,0xD581U,0x1540U,0xD701U,0x17C0U,0x1680U,0xD641U,
    0xD201U,0x12C0U,0x1380U,0xD341U,0x1100U,0xD1C1U,0xD081U,0x1040U,
    0xF001U,0x30C0U,0x3180U,0xF141U,0x3300U,0xF3C1U,0xF281U,0x3240U,
    0x3600U,0xF6C1U,0xF781U,0x3740U,0xF501U,0x35C0U,0x3480U,0xF441U,
    0x3C00U,0xFCC1U,0xFD81U,0x3D40U,0xFF01U,0x3FC0U,0x3E80U,0xFE41U,
    0xFA01U,0x3AC0U,0x3B80U,0xFB41U,0x3900U,0xF9C1U,0xF881U,0x3840U,
    0x2800U,0xE8C1U,0xE981U,0x2940U,0xEB01U,0x2BC0U,0x2A80U,0xEA41U,
    0xEE01U,0x2EC0U,0x2F80U,0xEF41U,0x2D00U,0xEDC1U,0xEC81U,0x2C40U,
    0xE401U,0x24C0U,0x2580U,0xE541U,0x2700U,0xE7C1U,0xE681U,0x2640U,
    0x2200U,0xE2C1U,0xE381U,0x2340U,0xE101U,0x21C0U,0x2080U,0xE041U,
    0xA001U,0x60C0U,0x6180U,0xA141U,0x6300U,0xA3C1U,0xA281U,0x6240U,
    0x6600U,0xA6C1U,0xA781U,0x6740U,0xA501U,0x65C0U,0x6480U,0xA441U,
    0x6C00U,0xACC1U,0xAD81U,0x6D40U,0xAF01U,0x6FC0U,0x6E80U,0xAE41U,
    0xAA01U,0x6AC0U,0x6B80U,0xAB41U,0x6900U,0xA9C1U,0xA881U,0x6840U,
    0x7800U,0xB8C1U,0xB981U,0x7940U,0xBB01U,0x7BC0U,0x7A80U,0xBA41U,
    0xBE01U,0x7EC0U,0x7F80U,0xBF41U,0x7D00U,0xBDC1U,0xBC81U,0x7C40U,
    0xB401U,0x74C0U,0x7580U,0xB541U,0x7700U,0xB7C1U,0xB681U,0x7640U,
    0x7200U,0xB2C1U,0xB381U,0x7340U,0xB101U,0x71C0U,0x7080U,0xB041U,
    0x5000U,0x90C1U,0x9181U,0x5140U,0x9301U,0x53C0U,0x5280U,0x9241U,
    0x9601U,0x56C0U,0x5780U,0x9741U,0x5500U,0x95C1U,0x9481U,0x5440U,
    0x9C01U,0x5CC0U,0x5D80U,0x9D41U,0x5F00U,0x9FC1U,0x9E81U,0x5E40U,
    0x5A00U,0x9AC1U,0x9B81U,0x5B40U,0x9901U,0x59C0U,0x5880U,0x9841U,
    0x8801U,0x48C0U,0x4980U,0x8941U,0x4B00U,0x8BC1U,0x8A81U,0x4A40U,
    0x4E00U,0x8EC1U,0x8F81U,0x4F40U,0x8D01U,0x4DC0U,0x4C80U,0x8C41U,
    0x4400U,0x84C1U,0x8581U,0x4540U,0x8701U,0x47C0U,0x4680U,0x8641U,
    0x8201U,0x42C0U,0x4380U,0x8341U,0x4100U,0x81C1U,0x8081U,0x4040U,
    };

    while (size > 0)
    {
        crc = table[*data ^ (uint8_t)crc] ^ (crc >> 8);
        data++;
        size--;
    }

    return crc;
}

// polynomial: 0x131, bit reverse algorithm
uint8_t Utils_Crc8(const void *data, unsigned int size)
{
    uint8_t crc = 0xff;
    const uint8_t *vdata = data;
    static const uint8_t table[256] = {
    0x00, 0x5E, 0xBC, 0xE2, 0x61, 0x3F, 0xDD, 0x83,
    0xC2, 0x9C, 0x7E, 0x20, 0xA3, 0xFD, 0x1F, 0x41,
    0x9D, 0xC3, 0x21, 0x7F, 0xFC, 0xA2, 0x40, 0x1E,
    0x5F, 0x01, 0xE3, 0xBD, 0x3E, 0x60, 0x82, 0xDC,
    0x23, 0x7D, 0x9F, 0xC1, 0x42, 0x1C, 0xFE, 0xA0,
    0xE1, 0xBF, 0x5D, 0x03, 0x80, 0xDE, 0x3C, 0x62,
    0xBE, 0xE0, 0x02, 0x5C, 0xDF, 0x81, 0x63, 0x3D,
    0x7C, 0x22, 0xC0, 0x9E, 0x1D, 0x43, 0xA1, 0xFF,
    0x46, 0x18, 0xFA, 0xA4, 0x27, 0x79, 0x9B, 0xC5,
    0x84, 0xDA, 0x38, 0x66, 0xE5, 0xBB, 0x59, 0x07,
    0xDB, 0x85, 0x67, 0x39, 0xBA, 0xE4, 0x06, 0x58,
    0x19, 0x47, 0xA5, 0xFB, 0x78, 0x26, 0xC4, 0x9A,
    0x65, 0x3B, 0xD9, 0x87, 0x04, 0x5A, 0xB8, 0xE6,
    0xA7, 0xF9, 0x1B, 0x45, 0xC6, 0x98, 0x7A, 0x24,
    0xF8, 0xA6, 0x44, 0x1A, 0x99, 0xC7, 0x25, 0x7B,
    0x3A, 0x64, 0x86, 0xD8, 0x5B, 0x05, 0xE7, 0xB9,
    0x8C, 0xD2, 0x30, 0x6E, 0xED, 0xB3, 0x51, 0x0F,
    0x4E, 0x10, 0xF2, 0xAC, 0x2F, 0x71, 0x93, 0xCD,
    0x11, 0x4F, 0xAD, 0xF3, 0x70, 0x2E, 0xCC, 0x92,
    0xD3, 0x8D, 0x6F, 0x31, 0xB2, 0xEC, 0x0E, 0x50,
    0xAF, 0xF1, 0x13, 0x4D, 0xCE, 0x90, 0x72, 0x2C,
    0x6D, 0x33, 0xD1, 0x8F, 0x0C, 0x52, 0xB0, 0xEE,
    0x32, 0x6C, 0x8E, 0xD0, 0x53, 0x0D, 0xEF, 0xB1,
    0xF0, 0xAE, 0x4C, 0x12, 0x91, 0xCF, 0x2D, 0x73,
    0xCA, 0x94, 0x76, 0x28, 0xAB, 0xF5, 0x17, 0x49,
    0x08, 0x56, 0xB4, 0xEA, 0x69, 0x37, 0xD5, 0x8B,
    0x57, 0x09, 0xEB, 0xB5, 0x36, 0x68, 0x8A, 0xD4,
    0x95, 0xCB, 0x29, 0x77, 0xF4, 0xAA, 0x48, 0x16,
    0xE9, 0xB7, 0x55, 0x0B, 0x88, 0xD6, 0x34, 0x6A,
    0x2B, 0x75, 0x97, 0xC9, 0x4A, 0x14, 0xF6, 0xA8,
    0x74, 0x2A, 0xC8, 0x96, 0x15, 0x4B, 0xA9, 0xF7,
    0xB6, 0xE8, 0x0A, 0x54, 0xD7, 0x89, 0x6B, 0x35,
    };

    while (size > 0)
    {
        crc = table[*vdata ^ crc];
        vdata++;
        size--;
    }

    return crc;
}

/**
 * 线性插值
 * @param x0 第0点的x坐标
 * @param y0 第0点的y坐标
 * @param x1 第1点的x坐标
 * @param y1 第1点的y坐标
 * @param x  待插值点的x坐标
 * @return   待插值点的y坐标
 */
float Utils_Interpolate(float x0, float y0, float x1, float y1, float x)
{
    float y;

    y = y0 + (x - x0) * (y1 - y0) / (x1 - x0);

    return y;
}

int Utils_InterpolateInt(int x0, int y0, int x1, int y1, int x)
{
    int y;

    y = y0 + (x - x0) * (y1 - y0) / (x1 - x0);

    return y;
}

long Utils_StrToNumber(const char *str)
{
    int base = 10;

    if((strlen(str) > 2) && ((str[0] == '0') && isalpha((unsigned char)str[1])))
    {
        switch(tolower(str[1]))
        {
        case 'b':
            base = 2;
            break;

        case 'o':
            base = 8;
            break;

        case 'x':
            base = 16;
            break;

        default:
            break;
        }

        str += 2;
    }

    return strtol(str, NULL, base);
}

